package com.wlcb.jpower.chat.service.customer.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.wlcb.jpower.chat.dbs.dao.customer.TblCustomerMsgDao;
import com.wlcb.jpower.chat.dbs.dao.customer.mapper.TblCustomerMsgMapper;
import com.wlcb.jpower.chat.dbs.dao.matter.ChatMatterDao;
import com.wlcb.jpower.chat.dbs.dao.wxuser.WxUserInfoDao;
import com.wlcb.jpower.chat.entity.customer.TblCustomerMsg;
import com.wlcb.jpower.chat.entity.matter.TbChatMatter;
import com.wlcb.jpower.chat.entity.wxuser.WxUserInfo;
import com.wlcb.jpower.chat.service.customer.CustomerMsgService;
import com.wlcb.jpower.chat.service.customer.SpecialUserService;
import com.wlcb.jpower.constant.DBConstant;
import com.wlcb.jpower.im.model.DataPacket;
import com.wlcb.jpower.module.common.service.impl.BaseServiceImpl;
import com.wlcb.jpower.module.common.utils.DateUtil;
import com.wlcb.jpower.module.common.utils.Fc;
import com.wlcb.jpower.module.common.utils.StringUtil;
import com.wlcb.jpower.module.common.utils.constants.StringPool;
import com.wlcb.jpower.utils.WxMpInstance;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service("customerMsgServiceImpl")
public class CustomerMsgServiceImpl extends BaseServiceImpl<TblCustomerMsgMapper, TblCustomerMsg> implements CustomerMsgService {

    @Autowired
    private TblCustomerMsgDao customerMsgDao;
    @Autowired
    private WxUserInfoDao wxUserInfoDao;
    @Autowired
    private ChatMatterDao chatMatterDao;
    @Autowired
    private SpecialUserService specialUserService;

    @Override
    public List<TblCustomerMsg> find(TblCustomerMsg msg, Date startTime, Date endTime) {
        LambdaQueryWrapper<TblCustomerMsg> queryWrapper = new QueryWrapper<TblCustomerMsg>().lambda();
        queryWrapper.orderByDesc(TblCustomerMsg::getCreateTime);
        queryWrapper.eq(TblCustomerMsg::getIsDeleted, 0);
        Map<SFunction<TblCustomerMsg, ?>, Object> map = new HashMap<>();
        map.put(TblCustomerMsg::getCompleteCid, msg.getCompleteCid());
        map.put(TblCustomerMsg::getCurrentCid, msg.getCurrentCid());
        map.put(TblCustomerMsg::getFirstCid, msg.getFirstCid());
        map.put(TblCustomerMsg::getOpenid, msg.getOpenid());
        map.put(TblCustomerMsg::getId, msg.getId());
        map.put(TblCustomerMsg::getType, msg.getType());
        map.put(TblCustomerMsg::getAppid, msg.getAppid());
        map.put(TblCustomerMsg::getStatus, msg.getStatus());
        map.put(TblCustomerMsg::getScore, msg.getScore());
        map.put(TblCustomerMsg::getName, msg.getName());
        map.put(TblCustomerMsg::getAddress, msg.getAddress());
        map.put(TblCustomerMsg::getCity, msg.getCity());

        queryWrapper.allEq(map, false);
        long time = endTime.getTime() + 3600 * 1000 * 24 - 1;
        Date date = new Date(time);
        queryWrapper.between(true, TblCustomerMsg::getUpdateTime, DateUtil.formatDate(startTime), DateUtil.formatDateTime(date));
        List<TblCustomerMsg> list = customerMsgDao.list(queryWrapper);
        List<String> openids = new ArrayList<>();
        List<String> types = new ArrayList<>();

        for (TblCustomerMsg tblCustomerMsg : list) {
            openids.add(tblCustomerMsg.getOpenid());
            if (Fc.isNotBlank(tblCustomerMsg.getType())) {
                types.add(tblCustomerMsg.getType());
            }

        }

        if (openids.size() > 0) {
            List<WxUserInfo> wxUserInfos = wxUserInfoDao.list(new QueryWrapper<WxUserInfo>().lambda().in(WxUserInfo::getOpenid, openids));
            for (WxUserInfo wxUserInfo : wxUserInfos) {
                for (TblCustomerMsg tblCustomerMsg : list) {
                    if (wxUserInfo.getOpenid().equals(tblCustomerMsg.getOpenid())) {
                        tblCustomerMsg.setUserInfo(wxUserInfo);
                    }
                }
            }
        }

        if (types.size() > 0) {
            List<TbChatMatter> chatMatterList = chatMatterDao.list(new QueryWrapper<TbChatMatter>().lambda().eq(TbChatMatter::getIsDeleted, 0)
                    .in(TbChatMatter::getId, types));
            for (TbChatMatter chatMatter : chatMatterList) {
                for (TblCustomerMsg customerMsg : list) {
                    if (chatMatter.getId().equals(customerMsg.getType())) {
                        customerMsg.setTypeName(chatMatter.getName());
                    }
                }
            }
        }
        return list;
    }

    @Override
    public List<TblCustomerMsg> findList(String cid, Date startTime, Date endTime) {

        List<TblCustomerMsg> list = customerMsgDao.list(new QueryWrapper<TblCustomerMsg>().lambda()
                .orderByAsc(TblCustomerMsg::getCreateTime)
                .eq(TblCustomerMsg::getCompleteCid, cid)
                .between(true, TblCustomerMsg::getUpdateTime, DateUtil.beginOfDay(startTime), DateUtil.endOfDay(endTime)));
        if (list.size() > 0) {
            ArrayList<TblCustomerMsg> disList = list.stream().peek(msg->msg.setData(null)).collect(Collectors.collectingAndThen(Collectors.toCollection(()
                    -> new TreeSet<>(Comparator.comparing(TblCustomerMsg::getOpenid))), ArrayList::new));

            List<String> openids = new ArrayList<>();
            for (TblCustomerMsg tblCustomerMsg : disList) {
                openids.add(tblCustomerMsg.getOpenid());
                for (TblCustomerMsg customerMsg : list) {
                    if (tblCustomerMsg.getOpenid().equals(customerMsg.getOpenid())) {
                        if (Fc.isNotBlank(tblCustomerMsg.getData())) {
                            List<DataPacket> list2 = JSONObject.parseArray(tblCustomerMsg.getData(), DataPacket.class);
                            List<DataPacket> list1 = JSONObject.parseArray(customerMsg.getData(), DataPacket.class);
                            list2.addAll(list1);
                            tblCustomerMsg.setData(JSON.toJSONString(list2));
                        } else {
                            List<DataPacket> list1 = JSONObject.parseArray(customerMsg.getData(), DataPacket.class);
                            tblCustomerMsg.setData(JSON.toJSONString(list1));
                        }
                    }
                }
            }
            List<WxUserInfo> wxUserInfos = wxUserInfoDao.list(new QueryWrapper<WxUserInfo>().lambda().in(WxUserInfo::getOpenid, openids));
            for (TblCustomerMsg tblCustomerMsg : disList) {
                for (WxUserInfo wxUserInfo : wxUserInfos) {
                    if (tblCustomerMsg.getOpenid().equals(wxUserInfo.getOpenid())) {
                        tblCustomerMsg.setUserInfo(wxUserInfo);
                    }
                }
            }
            return disList;
        }
        return Collections.emptyList();
    }

    @Override
    public boolean modifyById(TblCustomerMsg msg) {
        return customerMsgDao.update(msg, new UpdateWrapper<TblCustomerMsg>().lambda()
                .eq(TblCustomerMsg::getId, msg.getId())
                .eq(TblCustomerMsg::getIsDeleted, 0));
    }

    @Override
    public List<WxUserInfo> findByCurrentCid(String currentCid) {
        List<TblCustomerMsg> list = customerMsgDao.list(new QueryWrapper<TblCustomerMsg>().lambda()
                .eq(TblCustomerMsg::getCurrentCid, currentCid)
                .in(TblCustomerMsg::getStatus, DBConstant.CustomerMsgEnum.ACCESSED.getType(),
                        DBConstant.CustomerMsgEnum.OFFLINEACCESSED.getType()));

        List<String> openids = new ArrayList<>();
        if (list.size() > 0) {
            for (TblCustomerMsg msg : list) {
                openids.add(msg.getOpenid());
            }
        }
        if (openids.size() > 0) {
            List<WxUserInfo> wxUserInfos = wxUserInfoDao.list(new QueryWrapper<WxUserInfo>().lambda().in(WxUserInfo::getOpenid, openids));

            for (WxUserInfo wxUserInfo : wxUserInfos) {
                for (TblCustomerMsg msg : list) {
                    if (msg.getOpenid().equals(wxUserInfo.getOpenid())) {
                        wxUserInfo.setDialogId(msg.getId());
                        wxUserInfo.setIsSpecial(msg.getIsSpecial() != 0);
                    }
                }
            }

            return wxUserInfos;
        }

        return Collections.emptyList();
    }

    @Override
    public List<String> findRecept(Date startTime, Date endTime) {
        LambdaQueryWrapper<TblCustomerMsg> queryWrapper = new QueryWrapper<TblCustomerMsg>().lambda();
        if (Fc.isNull(startTime) || Fc.isNull(endTime)) {
            startTime = new Date();
            endTime = new Date();
        }
        queryWrapper.between(true, TblCustomerMsg::getUpdateTime, DateUtil.beginOfDay(startTime), DateUtil.endOfDay(endTime));
        List<TblCustomerMsg> list = customerMsgDao.list(queryWrapper);
        List<String> cids = new ArrayList<>();
        if (list.size() > 0) {
            list.forEach(x -> {
                if (!Fc.isBlank(x.getCompleteCid())) {
                    cids.add(x.getCurrentCid());
                }
            });
        }
        return cids.stream().distinct().collect(Collectors.toList());
    }

    @Override
    public long findByCid(String cid) {
        return customerMsgDao.count(new QueryWrapper<TblCustomerMsg>().lambda()
                .eq(TblCustomerMsg::getCurrentCid, cid)
                .eq(TblCustomerMsg::getStatus, DBConstant.CustomerMsgEnum.ACCESSED.getType()));
    }

    @Override
    public String saveCustomerMsg(String openid, String appId) {
        try {
            TblCustomerMsg tblCustomerMsg = new TblCustomerMsg();
            tblCustomerMsg.setOpenid(openid);
            tblCustomerMsg.setAppid(appId);
            tblCustomerMsg.setMsgId(DateUtil.format(new Date(),"HHmmssSSS"));

            //获取wlj中用户信息
            WxMpUser wxMpUser = WxMpInstance.getWxMp().switchoverTo(appId).getUserService().userInfo(openid);
            if (Fc.notNull(wxMpUser)){
                tblCustomerMsg.setName(wxMpUser.getNickname());
                tblCustomerMsg.setAddress(StringUtil.concat(true,wxMpUser.getCountry(), StringPool.DASH, wxMpUser.getProvince(), StringPool.DASH, wxMpUser.getCity()));
                tblCustomerMsg.setCity(wxMpUser.getCity());
                tblCustomerMsg.setIsSpecial(specialUserService.findByOpenidAndAppid(openid, appId) == null ? 0 : 1);
            }
            customerMsgDao.save(tblCustomerMsg);
            return tblCustomerMsg.getId();
        } catch (WxErrorException e) {
            e.printStackTrace();
            return null;
        }
    }

    @Override
    public TblCustomerMsg findbyAppIdAndOpenid(String appId, String openid) {
        return customerMsgDao.getOne(new QueryWrapper<TblCustomerMsg>().lambda()
                .eq(TblCustomerMsg::getAppid, appId).eq(TblCustomerMsg::getOpenid, openid)
                .eq(TblCustomerMsg::getStatus, DBConstant.CustomerMsgEnum.WAIT_ACCESS.getType()), false);
    }
}
